# -*- coding: utf-8 -*-
# created on 2017/3/1
# 

from mathsolver.functions.base import *
from mathsolver.functions.base.base import new_latex
from sympy import Poly, expand
from mathsolver.functions.hanshu.base import yici_judge
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve
from mathsolver.functions.erxiangshi.basic import exs_search_multiple, get_mul_coeff


# 求展开式第r+1项的系数
class EXSRCoeff(BaseFunction):
    def solver(self, *args):  # in: comm, r; out: baseValue(coef)
        erxiangshi_exs = self.search(str('exs'))
        comm = erxiangshi_exs.common()
        comm = comm.sympify()
        r = args[0].sympify()[0]
        sub_comm = comm.subs({Symbol("r"): r - 1})
        coeff = BaseValue(get_mul_coeff(sub_comm))
        self.steps.append(["", "第%s项的二项式系数为: %s" % (new_latex(r), coeff.printing())])
        self.output.append(coeff)
        self.label.add("求展开式的系数")
        return self


# 求系数和
class EXSRsCoeffSums(BaseFunction):
    def solver(self, *args):
        rs = args[0].sympify()
        coeffs = []
        for r in rs:
            coeff = EXSRCoeff(self.known).solver(BaseNumber(r)).output[0].sympify()
            coeffs.append(coeff)
        coefffs_sum = sum(coeffs)
        self.steps.append(["", "∴系数和为%s" % (new_latex(coefffs_sum))])
        self.output.append(BaseNumber(coefffs_sum))
        return self


# 求展开式第r+1项的二项系数
class EXSREXCoeff(BaseFunction):
    def solver(self, *args):  # in: 输入baseSympbol_value({a:,b:,n:}), r; out: BaseValues()
        if len(args) == 1:
            r = args[0].sympify()
        else:
            raise Exception("to do")
        er_xiang_shi = self.search('exs')
        e_n = er_xiang_shi.n
        if isinstance(r, list):
            coeff = BaseValue(binomial(e_n, r[0] - 1))
            self.steps.append(["", "第%s项的二项式系数为: %s" % (new_latex(r[0] + 1), coeff.printing())])
        else:
            coeff = BaseValue(binomial(e_n, r - 1))
            self.steps.append(["", "第%s项的二项式系数为: %s" % (new_latex(r + 1), coeff.printing())])
        self.output.append(BaseNumber(coeff.sympify()))
        self.label.add("求展开式的二项式系数")
        return self


# 求展开式二项式系数最大的项的r
class EXSMaxEXCoeffR(BaseFunction):  # 求展开式二项式系数最大的项的r
    def solver(self, *args):  # in: a,b,n
        if not args:
            er_xiang_shi = self.search(str('exs'))
            e_n = er_xiang_shi.n
        else:
            raise Exception("to do")
        if e_n.free_symbols:
            if yici_judge(e_n):
                symbols = e_n.free_symbols
                symbol = symbols.pop()
                poly = Poly(e_n.as_expr(), symbol)
                a, b = poly.all_coeffs()
                if (a % 2) == 0 and (b % 2) == 0:
                    nums = [e_n / 2 + 1]
                    self.steps.append(["", "二项式系数最大的项为第%s项" % new_latex(nums[0])])
                elif (a % 2) == 0 and (b % 2) == 1:
                    nums = [(e_n + 1) / 2, (e_n - 1) / 2]
                    self.steps.append(["", "二项式系数最大的项为第%s,%s项" % (new_latex(nums[0]), new_latex(nums[1]))])
        else:
            if (e_n % 2) == 1:  # 奇数
                nums = [(e_n + 1) / 2, (e_n - 1) / 2]
                self.steps.append(["", "二项式系数最大的项为第%s,%s项" % (new_latex(nums[0]), new_latex(nums[1]))])
            else:
                nums = [e_n / 2 + 1]
                self.steps.append(["", "二项式系数最大的项为第%s项" % new_latex(nums[0])])
        self.output.append(BaseNumbers(nums))
        self.label.add("求展开式二项系数最大的项")
        return self


# 求系数为有理数的项
class EXSYouLiCoeffR(BaseFunction):
    def solver(self, *args):  # in: comm, out: BaseNumber: 个数
        if not args:
            erxiangshi_exs = self.search(str('exs'))
            comm = erxiangshi_exs.common()
            comm = comm.sympify()
        else:
            raise Exception("to do")
        pow_dict = comm.as_powers_dict()
        nn = -1
        for k, v in pow_dict.items():
            if isinstance(k, binomial):
                nn = k.args[0]
        rs = []
        for r in range(nn + 1):
            coeff = get_mul_coeff(comm.subs({Symbol("r"): r}))
            if coeff.is_Rational:
                rs.append(r + 1)
        self.steps.append(["", "系数为有理数的项分别是第%s项" % ",".join([new_latex(num) for num in rs])])
        self.output.append(BaseNumbers(rs))
        self.label.add("求系数为有理数的项")
        return self


# 求系数最大的项的r
class EXSMaxCoeffR(BaseFunction):
    def solver(self, *args):  # in: a,b,n; out: BaseNumber
        if not args:
            erxiangshi_coeff = self.search(str('exs'))
            e_a = erxiangshi_coeff.a
            e_b = erxiangshi_coeff.b
            e_n = erxiangshi_coeff.n
        else:
            raise Exception("to do")
        e_r = Symbol("r")
        coef = binomial(e_n, e_r)
        coef_a = get_mul_coeff(e_a)
        coef_b = get_mul_coeff(e_b)
        coeff = coef * simplify(coef_a ** (e_n - e_r) * coef_b ** e_r)
        coeff_p = coeff.subs({e_r: e_r + 1})
        coeff_d = coeff.subs({e_r: e_r - 1})
        ineqs = BaseIneqs([[coeff, ">=", coeff_p], [coeff, ">=", coeff_d]])
        self.steps.append(["", "依题意，得"])
        self.steps.append(["", "%s" % ineqs.printing()])
        exs = erxiangshi_coeff.instance(e_a, e_b, e_n)
        big_index = exs.the_max_coeff()
        self.steps.append(["", "解得: %s" % (BaseSymbolValue({e_r: big_index}).printing())])
        if len(big_index) == 1:
            index = BaseNumber(big_index[0])
            self.steps.append(["", "系数最大的项为第%s项" % index.printing()])
        else:
            index = BaseNumbers(big_index)
            self.steps.append(["", "系数最大的项为%s项" % index.printing()])
        self.output.append(index)
        self.label.add("求系数最大的项")
        return self


# 求系数最小项的r
class ExsMinCoeffR(BaseFunction):
    def solver(self, *args):  # in: a,b,n; out: BaseNumber
        if not args:
            erxiangshi_exs = self.search(str('exs'))
            e_a = erxiangshi_exs.a
            e_b = erxiangshi_exs.b
            e_n = erxiangshi_exs.n
        else:
            raise Exception("to do")
        e_r = Symbol("r")
        coef = binomial(e_n, e_r)
        coef_a = get_mul_coeff(e_a)
        coef_b = get_mul_coeff(e_b)
        coeff = coef * simplify(coef_a ** (e_n - e_r) * coef_b ** e_r)
        coeff_p = coeff.subs({e_r: e_r + 1})
        coeff_d = coeff.subs({e_r: e_r - 1})
        ineqs = BaseIneqs([[coeff, "<=", coeff_p], [coeff, "<=", coeff_d]])
        self.steps.append(["", "依题意，得"])
        self.steps.append(["", "%s" % ineqs.printing()])
        exs = erxiangshi_exs.instance(e_a, e_b, e_n)
        min_index = exs.the_min_coeff()
        self.steps.append(["", "解得: %s" % (BaseSymbolValue({e_r: min_index}).printing())])
        if len(min_index) == 1:
            index = BaseNumber(min_index[0])
            self.steps.append(["", "系数最小的项为第%s项" % index.printing()])
        else:
            index = BaseNumbers(min_index)
            self.steps.append(["", "系数最小的项为%s项" % index.printing()])
        self.output.append(index)
        self.label.add("求系数最小的项")
        return self


# 根据项，求系数
class EXSPolyCoeff(BaseFunction):
    def solver(self, *args):  # in: base_poly, poly, out: coeff
        erxiangshi_exs = self.search(str('exs'))
        if hasattr(erxiangshi_exs, 'n'):
            n_value = self.search(erxiangshi_exs.n)
            if n_value is not None:
                erxiangshi_exs.n = n_value.args[0]
        base_poly = erxiangshi_exs.poly
        base_poly = simplify(base_poly)
        poly_ed = base_poly.expand()
        if str(poly_ed) != str(base_poly):
            poly = args[0].sympify()
            if not poly_ed.is_Add:
                base_poly, poly = poly, base_poly
                poly_ed = base_poly.expand()
            poly = str(poly)
            poly_ed = str(poly_ed)
            coef = sympify(poly_ed).coeff(sympify(poly))
            self.steps.append(["", "%s的系数为：%s" % (new_latex(sympify(poly)), new_latex(coef))])
            self.output.append(BaseNumber(coef))
        else:
            comm_poly = erxiangshi_exs.common()
            comm_poly = comm_poly.sympify()
            comm_name = sympify('T_(r+1)')
            self.steps.append(["", "%s = %s" % (new_latex(comm_name), new_latex(comm_poly))])
            comm_poly_dict = comm_poly.as_powers_dict()
            poly = args[0].sympify()
            poly = simplify(poly)
            poly_dict = poly.as_powers_dict()
            eqs = []
            for k1, v1 in poly_dict.items():
                for k2, v2 in comm_poly_dict.items():
                    if k1 == k2:
                        eqs.append([v1, v2])
            self.steps.append(["", "依题意, 得"])
            if len(eqs) == 1:
                self.steps.append(["", "%s" % (BaseEq(eqs[0]).printing())])
            else:
                self.steps.append(["", "%s" % (BaseEqs(eqs).printing())])
            solutions = MathematicaSolve().solver(BaseIneqs(eqs), BaseVariable("r")).output[0].sympify()
            self.steps.append(["", "解得: %s" % (BaseSymbolValue(solutions).printing())])
            answers = exs_search_multiple(solutions, comm_poly)
            assert answers
            comm_poly_coeffs = []
            for ans in answers:
                new_value = comm_poly
                new_value = new_value.subs(ans)
                new_value = new_value.expand().simplify()
                new_coeff = get_mul_coeff(new_value)
                comm_poly_coeffs.append(new_coeff)
            if len(comm_poly_coeffs) == 1:
                comm_poly_coeff = comm_poly_coeffs[0]
                self.steps.append(["", "∴ %s = %s" % (new_latex(comm_name), new_latex(comm_poly_coeff))])
                self.output.append(BaseNumber(comm_poly_coeff))
        self.label.add("求展开式中某项系数")
        return self


# 使(3x+\\frac{1}{x\\sqrt x })^n的展开式中含有常数项的最小的n为 ()
class EXSConstPolyMinN(BaseFunction):
    def solver(self, *args):
        erxiangshi_exs = self.search(str('exs'))
        variable = args[0].sympify()
        if erxiangshi_exs.flag:
            comm = erxiangshi_exs.common()
            poly = comm.sympify()
            poly = sympify(poly)
            pow_dict = poly.as_powers_dict()
            eqs = []
            for k, v in pow_dict.items():
                if k in {x, y}:
                    eqs.append([v, S.Zero])
            if len(eqs) == 1:
                self.steps.append(["", "∴%s" % (BaseEq(eqs[0]).printing())])
            else:
                self.steps.append(["", "∴%s" % (BaseEqs(eqs).printing())])
            solutions = MathematicaSolve().solver(BaseIneqs(eqs), BaseVariable("r")).output[0]
            self.steps.append(["", "解得: %s" % (solutions.printing())])
            answers = exs_search_multiple(solutions.sympify(), sympify("r"))
            target_r_values = []
            for ans in answers:
                target_r = sympify("r")
                target_r = target_r.subs(ans)
                target_r_values.append(target_r)
            min_value = None
            for target_r_value in target_r_values:
                target_r_value_symbols = target_r_value.free_symbols
                target_r_value_symbols = list(target_r_value_symbols)
                assert len(target_r_value_symbols) == 1
                target_r_value_symbol = target_r_value_symbols[0]
                assert str(variable) == str(target_r_value_symbol)
                for i in range(1, 100):
                    new_target_r_value = target_r_value.subs({variable: i})
                    if new_target_r_value.is_Integer:
                        min_value = i
                        break
            assert min_value
            self.steps.append(["", "∴最小的%s为%s" % (new_latex(variable), new_latex(min_value))])
            self.output.append(BaseValue(min_value))
        else:
            poly = erxiangshi_exs.poly
            poly = simplify(poly)
            poly = expand(poly)
            if len(args) == 2:
                sym = args[1].value2pairs()[0]
                poly = poly.subs(sym)
            const = poly.as_coeff_Add()[0]
            self.steps.append(["", "常数项为: %s" % new_latex(const)])
            self.output.append(BaseNumber(const))
        self.label.add("求含有常数项的最小的n")
        return self


if __name__ == '__main__':
    pass
